﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using AvalonDock;
using ReflectionStudio.Classes.Workspace;
using ReflectionStudio.Components.UserControls;
using ReflectionStudio.Core.Events;
using ReflectionStudio.Core.FileManagement;
using ReflectionStudio.Classes;
namespace ReflectionStudio.Classes
{
	public class DocumentFactory
	{
		#region ----------------SINGLETON----------------
		/// <summary>
		/// Singleton
		/// </summary>
		public static readonly DocumentFactory Instance = new DocumentFactory();

		/// <summary>
		/// Private constructor for singleton pattern
		/// </summary>
        public DocumentFactory()
		{
		}
		#endregion

		#region ---------------------PRIVATE---------------------

        public DockingManager _DockManager = null;

		#endregion

		#region ----------------PROPERTIES----------------


		public DocumentBase ActiveDocument
		{
			get { return _DockManager.ActiveDocument as DocumentBase; }
		}

		List<SupportedDocumentInfo> _SupportedDocuments = new List<SupportedDocumentInfo>();
		public List<SupportedDocumentInfo> SupportedDocuments
		{
			get { return _SupportedDocuments; }
		}

		#endregion

		#region ----------------METHODS----------------

		public void Initialize(DockingManager dockManager)
		{
			_DockManager = dockManager;

			InitSupportedDocuments();
		}

		internal SupportedDocumentInfo GetSupportedDocumentInfo(DocumentBase docInstance)
		{
			return _SupportedDocuments.Find(p => p.DocumentContentType == docInstance.GetType());
		}

		internal string GetAllSupportedFilter()
		{
			string result = string.Empty;

			foreach( string item in _SupportedDocuments.Where(p => !string.IsNullOrEmpty(p.DialogFilter)).Select(p=>p.DialogFilter).Distinct() )
				result += item + "|";

			return result.Remove( result.Length-1 );
		} 
		public DocumentBase CreateDocument(SupportedDocumentInfo info, IDocumentDataContext context = null)
		{
			return GetDocument(info, context, true,null);
		}

         
		public void OpenDocument( DiskContent dc )
		{
			SupportedDocumentInfo info = SupportedDocuments.Find(p => p.Extension == dc.Extension);
			if (info != null)
			{
				IDocumentDataContext context = (IDocumentDataContext)Activator.CreateInstance(info.DocumentDataType);
				context.FullName = dc.FullName;
				GetDocument(info, context, true,null);
			}
		}

        public void OpenDocument(SupportedDocumentInfo info, IDocumentDataContext context, Dictionary<string, object> dicParamater)
		{
			//WorkspaceService.Instance.AddRecentFile(context.FullName);

            GetDocument(info, context, true, dicParamater);
		}
 

		#endregion

		#region ---------------------EVENTS---------------------

		private void DocumentClosing(object sender, CancelEventArgs e)
		{
			DocumentBase db = sender as DocumentBase;

			Tracer.Verbose("DocumentFactory.DocumentClosing", db.Title + " closing");

			//manage dirty state ?
		}

		private void DocumentClosed(object sender, EventArgs e)
		{
            return;
			DocumentBase db = sender as DocumentBase;

			Tracer.Verbose("DocumentFactory.DocumentClosed", db.Title + " closed");

			if( GetSupportedDocumentInfo(db).CanCreate )
				WorkspaceService.Instance.AddRecentFile(db.Context.FullName);
		}

		#endregion
		
		#region ----------------INTERNALS----------------

		private DocumentBase GetDocument(SupportedDocumentInfo docInfo)
		{
			return GetDocument(docInfo, null, true,null);
		}
        public DocumentBase CreateDocument(Type docType, IDocumentDataContext context = null)
        {
            ///return GetDocument(_SupportedDocuments.Find(p => p.DocumentContentType == docType), context, true);
            return OpenDocument(docType, context,null);
        }
        public DocumentBase OpenDocument(Type docType, IDocumentDataContext context, Dictionary<string, object> dicParamater)
        {
            WorkspaceService.Instance.AddRecentFile(context.FullName);
            SupportedDocumentInfo sdoc = _SupportedDocuments.Find(p => p.DocumentContentType == docType);
            if (sdoc == null)
            {
                _SupportedDocuments.Add(new SupportedDocumentInfo()
                {
                    CanCreate = true,
                    ShortDescription = docType.ToString(),
                    LongDescription = "报表条件",
                    Image = "/IntexReportClient;component/Resources/Images/16x16/LanSunStudio.png",
                    DocumentContentType = docType,
                    DocumentContentGUID = docType.Name,
                    Counter = 0,
                    Extension = ".rst",
                    DefaultTitle = "报表条件{0}"
                });
            }
            sdoc = _SupportedDocuments.Find(p => p.DocumentContentType == docType);
            DocumentBase doc = GetDocument(sdoc, context, true, dicParamater);
            return doc;
        }
        private DocumentBase GetDocument(SupportedDocumentInfo docInfo, IDocumentDataContext context, bool activate, Dictionary<string, object> dicParamater)
		{
			//Tracer.Verbose("DocumentFactory:GetDocument", "docName{0}, docTitle{0}, docType{0}, activate{0}", docName, docTitle, docType, activate);

			DocumentBase doc = FindDocument(docInfo, context);

			try
			{
				if (doc == null)
					doc = CreateNewDocument(docInfo, context,dicParamater);

                if (doc != null && activate)
                    _DockManager.ActiveDocument = doc;
			}
			catch (Exception ex)
			{
                Tracer.Error(ex.StackTrace, ex);
			}
			finally
			{
				Tracer.Verbose("DocumentFactory:GetDocument", "END");
			}

			return doc;
		}

        private DocumentBase CreateNewDocument(SupportedDocumentInfo docInfo, IDocumentDataContext context, Dictionary<string, object> dicParamater)
        {
			//Tracer.Verbose("DocumentFactory:CreateDocument", "docName{0}, docTitle{0}, docType{0}, activate{0}", docName, docTitle, docType, activate);

			DocumentBase doc = null;
            
            try
            {
				doc = (DocumentBase)Activator.CreateInstance(docInfo.DocumentContentType);

                if( doc != null )
                {
					if (string.IsNullOrEmpty(context.FullName))
					{
						doc.Title = string.Format(doc.Name, docInfo.Counter++);
						doc.ToolTip = doc.Title;
					}
                    doc.SetUp(dicParamater);
					doc.Name = docInfo.DocumentContentGUID;
                    doc.DataContext = context;

                    doc.Closing += new EventHandler<CancelEventArgs>(DocumentClosing);
                    doc.Closed += new EventHandler(DocumentClosed);

                    _DockManager.MainDocumentPane.Items.Add(doc);
                }
            }
            catch (Exception ex)
            {
                Tracer.Error(ex.StackTrace, ex);
            }
            finally
            {
				Tracer.Verbose("DocumentFactory:CreateDocument", "END");
            }
            return doc;
        }

		private DocumentBase FindDocument(SupportedDocumentInfo docInfo, IDocumentDataContext context)
        {
            IEnumerable<DocumentContent> list = _DockManager.Documents.Where(d => d.Name == docInfo.DocumentContentGUID && d.Title == context.Name);
			if (list.Count() == 1)
				return list.First() as DocumentBase;
			else
				return null;
        }

		internal void InitSupportedDocuments()
		{ 
			_SupportedDocuments.Add(new SupportedDocumentInfo()
			{
				CanCreate = true,
				ShortDescription = "Diagram",
				LongDescription = "Assembly and class diagram",
				Image = "/IntexReportClient;component/Resources/Images/16x16/template.png",
				//DocumentContentType = typeof(ProjectDocument),
				//DocumentDataType = typeof(),
                DocumentContentGUID = "_DocDiagram",
				Counter = 0,
				Extension = ".rsd",
				DialogExtension = "*.rsd",
				DialogFilter = "Diagram files (*.rsd)|*.rsd",
				DefaultTitle = "Diagram {0}"
			}); 
		}

		#endregion
	}
}
